home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmartin-2.2 / xmartin.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  28KB  |  925 lines

  1. /*
  2.  *   xmartin - set root window to Martin hopalong pattern
  3.  *
  4.  *   xmartin [-f {martin1|martin2|ejk1|...|ejk6|rr1|cp1[,order[,xn,yn]]]}
  5.  *           [-p npoints] [-P npoints] 
  6.  *           [-a value[:[:]value]] [-b value[:[:]value]] [-c value[:[:]value]]
  7.  *           [-d value[:[:]value]] [-x value[:[:]value]] [-y value[:[:]value]]
  8.  *           [-nc npoints] [-dynam [npoints]] [-static]
  9.  *           [-tile [XxY]] [-perturb [n[,v]]] [-coord {xy|yx|ra|ar}]
  10.  *           [-zoom real] [-move d,p]
  11.  *           [-recall] [-display display]
  12.  *           [+rv] [-rv] [-bg [color[,intensity]]]
  13.  *           [-v]
  14.  *
  15.  *   -f function : martin1|martin2|ejk1|...|ejk6|rr1|cp1
  16.  *   -p npoints  : maximum in-range points   [25% of display/tile pixels]
  17.  *   -P npoints  : maximum total points to calculate   [3 x -p value]
  18.  *   -a -b -c -d -x -y  : real values for hopalong parameters   [random]
  19.  *   -dynam [nd] : flush after nd points   [1024, 128 if -tile]
  20.  *   -static     : calculate all points before display
  21.  *   -tile [XxY] : tiling factors   [random if XxY omitted]
  22.  *   -perturb [n,v] : perturb (x,y) every n points by v  [random if n,v omitted]
  23.  *   -coord xx   : coordinate mode - xy | yx | ra | ar
  24.  *   -zoom real  : zoom factor   [1.0, 4.0 if martin2]
  25.  *   -move d,p   : moves pattern p pixels in direction d. d is a compass
  26.  *                 heading in degrees or 'n', 'sw', 'nnw' etc
  27.  *   -recall     : recalls f, abcdxy, zoom, move, tile & perturb values from 
  28.  *                 last plot before processing other arguments
  29.  *   -nrc        : turns off randomizing of color sequences
  30.  *   -nc npoints : points calculated before color change   [(-P value)/ncolors]
  31.  *   -mono       : forces white-on-black for grayscale or color displays
  32.  *   -rv +rv     : reverse video on/off  [-rv (on)]
  33.  *   -bg color[,intensity] : background color  [random]
  34.  *   -v          : print version & patchlevel
  35.  *
  36.  *   Hopalong was attributed to Barry Martin of Aston University (Birmingham, 
  37.  *   England) by A. K. Dewdney in the Septmber 86 Scientific American. 
  38.  * 
  39.  *   The cp1 sine sculptures were published by Clifford Pickover in the 
  40.  *   January 91 Algorithm. The rr1 generalized exponent version of the 
  41.  *   martin1 square root was developed by Renaldo Recuerdo of the Santa Cruz
  42.  *   Operation.
  43.  ^
  44.  *   The ranf random number generator is based on work by D. H. Lehmer, Knuth,
  45.  *   David Sachs(Fermilab) and Curt Canada(NCSA).
  46.  *
  47.  *   This software is provided "as is" and with no warranties of any kind.
  48.  *
  49.  *   Ed Kubaitis
  50.  *   Computing Services Office
  51.  *   University of Illinois, Urbana
  52.  */
  53.  
  54. #include <X11/Xos.h>
  55. #include <X11/Xlib.h>
  56. #include <math.h>
  57. #include <stdio.h>
  58. #include "patchlevel.h"
  59.  
  60. #define Min(x,y) ((x < y)?x:y)
  61. #define Max(x,y) ((x > y)?x:y)
  62. #define Fmod1(p) ((p) - (long)(p))
  63.  
  64. #define Msg(fmt) fprintf(stderr,fmt)
  65. #define Msg1(fmt,a) fprintf(stderr,fmt,a)
  66. #define Msg2(fmt,a,b) fprintf(stderr,fmt,a,b)
  67. #define Msg3(fmt,a,b,c) fprintf(stderr,fmt,a,b,c)
  68. #define Msg4(fmt,a,b,c,d) fprintf(stderr,fmt,a,b,c,d)
  69.  
  70. int     mxp=0, np=0;             /* max in-range points, in-range points    */
  71. int     mxP=0, nP=0;             /* max total points,    total points       */
  72. int     nC=0, nc=0;              /* color-change interval (points)          */
  73. int     nD=0, nd=0;              /* flush buffer interval (points)          */
  74. int     Pn=0, pn=0;              /* seed perturbation interval (points)     */
  75. double  Pv=0;                    /* seed perturbation value                 */
  76.  
  77. double  A=0, B=0, C=0, D=0, x=0, y=0; /* hopalong parameters                */
  78. int     Color=0;                 /* non-zero if color                       */
  79. int     Dynam=1;                 /* non-zero to display-as-calculated       */
  80. int     Randomcolor=1;           /* non-zero for randomized color sequences */
  81. int     Coord=0;                 /* coordinate mode 0:xy 1:yx 2:ra 3:ar     */
  82. int     Tx=1, Ty=1;              /* tile factors                            */
  83. double  Zf=0;                    /* magnification factor                    */
  84. int     Recall=0;                /* non-zero if previous parms recalled     */
  85. int     CpOrder = 0;             /* Cp1 highest-order term (1->16)          */
  86. unsigned long CpXOrdinal;        /* Cp1 x permutation ordinal (<4**order)   */
  87. unsigned long CpYOrdinal;        /* Cp1 y permutation ordinal (<4**order)   */
  88.  
  89.  
  90. int cx, cy, ix, iy, mxX, mxY, col = 0;
  91. int bmn, wc, plane, offset, pixel, pix, bit;
  92. double pi, X0, Y0;
  93.  
  94. int Function = -1;
  95. #define Martin1 0
  96. #define Martin2 1
  97. #define Ejk1    2
  98. #define Ejk2    3
  99. #define Ejk3    4
  100. #define Ejk4    5
  101. #define Ejk5    6
  102. #define Ejk6    7
  103. #define Rr1     8
  104. #define Cp1     9
  105. #define Nfunc  10
  106.  
  107. char fname[Nfunc][16] = { 
  108.    "martin1", "martin2", 
  109.    "ejk1", "ejk2", "ejk3", "ejk4", "ejk5", "ejk6",
  110.    "rr1" , "cp1"
  111.    };
  112. double fprob[Nfunc] = {
  113.    .32,       .02,       
  114.    .08,    .03,    .06,    .06,    .06,    .06, 
  115.    .06,    .25
  116.    };
  117.  
  118.  
  119. #define Ncolors 16
  120. struct colors { unsigned long c_color; double c_rand; } colors[Ncolors];
  121.  
  122. char fg_colors[Ncolors][30] = { "red", "green", "blue", "yellow", "magenta", 
  123.    "cyan", "coral", "slate blue", "orange red", "spring green", "orange", 
  124.    "steel blue", "pink", "violet", "firebrick", "gold"};
  125.  
  126. char bg_colors[Ncolors][30] = { "black", "white,.20", "white,.25", "white,.30",
  127.    "white,.35", "blue,.20", "blue,.25", "blue,.30", "red,.25", "red,.30", 
  128.    "red,.35", "green,.25", "green,.30", "cyan,.20", "cyan,.25", "cyan,.30"};
  129.  
  130. char fg_grays[Ncolors][30] = { "white", "white,.96", "white,.92", 
  131.    "white,.88", "white,.84", "white,.80", "white,.76", "white,.72", 
  132.    "white,.68", "white,.64", "white,.60", "white,.56", "white,.52", 
  133.    "white,.48", "white,.44", "white,.40"};
  134.  
  135. char bg_grays[Ncolors][30] = { "black", "white,.02", "white,.04", 
  136.    "white,.06", "white,.08", "white,.10", "white,.12", "white,.14", 
  137.    "white,.16", "white,.18", "white,.20", "white,.22", "white,.24", 
  138.    "white,.26", "white,.28", "white,.30"};
  139.  
  140. char compass[16][4] = {
  141.    "n", "nne", "ne", "ene", "e", "ese", "se", "sse",
  142.    "s", "ssw", "sw", "wsw", "w", "wnw", "nw", "nnw" };
  143.  
  144. double cp_zoom[16] = {
  145.    200, 200, 175, 175, 150, 150, 125, 125, 
  146.    125, 100, 100,  80,  70,  60,  60,  60};
  147. char   cp_move[16][8] = {
  148.    "310,220", "310,220", "310,220", "310,220", "310,220", "310,320",
  149.    "310,320", "310,320", "310,320", "310,320", "310,320", "310,320",
  150.    "310,320", "310,320", "310,320", "310,320"};
  151.  
  152. double sine[4], xt, yt;
  153. #define Ax 0
  154. #define Ay 1
  155. #define Bx 2
  156. #define By 3
  157. int xi, yi, order, n;
  158. unsigned long xo, yo;
  159.  
  160. #define XY 0
  161. #define YX 1
  162. #define RA 2
  163. #define AR 3
  164. char coords[4][3] = { "xy", "yx", "ra", "ar" };
  165.  
  166. Display *dpy = NULL;       
  167. Window  w_root;
  168. int     W, H, DP, scr;   
  169. Pixmap  pixmap;
  170. GC      gc;
  171. XPoint  *xpoints;
  172. XImage  *Xi;
  173. char    *bmap;
  174.  
  175. char    Savefile[128]; FILE *sf;
  176. char    *Move = NULL;
  177. char    **Argv = NULL; int Argc = 0;
  178. time_t  t0;
  179.  
  180.  
  181. main(argc, argv) int argc; char *argv[]; {
  182.  
  183.    preset(argc, argv);
  184.    hopalong();
  185.    finish();
  186.    exit(0);
  187.  
  188.    }
  189. double ranf();
  190.  
  191. hopalong() {
  192.    double x1, y1;
  193.  
  194.    while (++nP < mxP) {
  195.  
  196.       if (Function == Martin1) {
  197.      x1 = y  - ( (x<0) ? sqrt(fabs(B*x-C)) : -sqrt(fabs(B*x-C)) );
  198.      y1 = A - x;
  199.      }
  200.       else if (Function == Martin2) {
  201.      x1 = y  - sin(x);
  202.      y1 = A - x;
  203.      }
  204.       else if (Function == Ejk1) {
  205.      x1 = y  - ( (x>0) ? (B*x-C) : -(B*x-C) );
  206.      y1 = A - x;
  207.      }
  208.       else if (Function == Ejk2) {
  209.      x1 = y  - ( (x<0) ? log(fabs(B*x-C)) : -log(fabs(B*x-C)) );
  210.      y1 = A - x;
  211.      }
  212.       else if (Function == Ejk3) {
  213.      x1 = y  - ( (x>0) ? sin(B*x) - C : -(sin(B*x) - C) );
  214.      y1 = A - x;
  215.      }
  216.       else if (Function == Ejk4) {
  217.      x1 = y  - ( (x>0) ? sin(B*x) - C : -sqrt(fabs(B*x-C)) );
  218.      y1 =  A - x;
  219.      }
  220.       else if (Function == Ejk5) {
  221.      x1 = y  - ( (x>0) ? sin(B*x) - C : -(B*x-C) );
  222.      y1 =  A - x;
  223.      }
  224.       else if (Function == Ejk6) {
  225.      x1 = y  - asin(Fmod1(B*x)); 
  226.      y1 =  A - x;
  227.      }
  228.       else if (Function == Rr1) {
  229.      x1 = y  - ( (x<0) ? -pow(fabs(B*x-C), D) : pow(fabs(B*x-C), D) );
  230.      y1 = A - x;
  231.      }
  232.       else if (Function ==  Cp1) {
  233.      xo = CpXOrdinal;
  234.      yo = CpYOrdinal;
  235.      x1 = 0; y1 = 0;
  236.  
  237.      sine[Ax] = sin(A*x); sine[Ay] = sin(A*y);
  238.      sine[Bx] = sin(B*x); sine[By] = sin(B*y);
  239.  
  240.      for (order=1; order <= CpOrder; order++) {
  241.         xt = 1; yt = 1;
  242.         xi = xo & 3; xo >>= 2;
  243.         yi = yo & 3; yo >>= 2;
  244.         for (n=0; n<order; n++) {
  245.            xt *= sine[xi]; 
  246.            yt *= sine[yi];
  247.            }
  248.         x1 += xt; y1 += yt;
  249.         }
  250.      }
  251.       x = x1; y = y1;
  252.  
  253.       if (Pn && ++pn > Pn) {
  254.      x += (x>0) ? -Pv : Pv;
  255.      y += (y>0) ? -Pv : Pv;
  256.      pn = 0;
  257.      }
  258.  
  259.       if (Color && ++nc > nC) {
  260.      col = (col+1)%Ncolors;
  261.      nc = 0;
  262.      if (Dynam) {
  263.         nd && drawpoints();
  264.         XSetForeground(dpy, gc, colors[col].c_color);
  265.         }
  266.      else pixel = colors[col].c_color;
  267.      }
  268.  
  269.       if (Coord == XY) {
  270.      iy = cy + Zf*y1;
  271.      ix = cx + Zf*x1;
  272.      }
  273.       else if (Coord == YX) {
  274.      iy = cy + Zf*x1;
  275.      ix = cx + Zf*y1;
  276.      }
  277.       else if (Coord == RA) {
  278.      iy = cy + Zf*x1*sin(y1);
  279.      ix = cx + Zf*x1*cos(y1);
  280.      }
  281.       else if (Coord == AR) {
  282.      iy = cy + Zf*y1*sin(x1);
  283.      ix = cx + Zf*y1*cos(x1);
  284.      }
  285.  
  286.       if (iy < 0 || iy > mxY) continue;
  287.       if (ix < 0 || ix > mxX) continue;
  288.  
  289.       if (Dynam) {
  290.      xpoints[nd].x = ix;
  291.      xpoints[nd].y = iy;
  292.      (++nd == nD) && drawpoints();
  293.      }
  294.       else {
  295. /*       XPutPixel(Xi, ix, iy, colors[color].c_color);  */    /* very slow */
  296.          pix = pixel;
  297.          for(plane=DP-1; plane>=0; plane--) {
  298.             bit = pix & 1;
  299.             offset = plane * wc * H + iy*wc + (ix>>3);
  300.             bmap[offset] &= ~(1<<(ix&7));
  301.             if (bit) bmap[offset] |= 1<<(ix&7);
  302.             pix >>= 1;
  303.             }
  304.          }
  305.      
  306.       if (++np >= mxp) break;
  307.       }
  308.    }
  309.  
  310.  
  311. drawpoints() {
  312.    XDrawPoints(dpy, pixmap, gc, xpoints, nd, CoordModeOrigin);
  313.    XClearWindow(dpy, w_root);
  314.    nd = 0;
  315.    }
  316.  
  317. finish() {
  318.  
  319.    nd && drawpoints();
  320.  
  321.    if (!Dynam) {
  322.       gc = XCreateGC(dpy, w_root, 0, (XGCValues *)0);
  323.       pixmap = XCreatePixmap( dpy, w_root, W, H, DP);
  324.       if (!pixmap) { Msg("xmartin: XCreatePixmap error\n"); exit(1);}
  325.       XPutImage(dpy, pixmap, gc, Xi, 0, 0, 0, 0, W, H);
  326.       XSetWindowBackgroundPixmap(dpy, w_root, pixmap);
  327.       XClearWindow(dpy, w_root);
  328.       XDestroyImage(Xi);
  329.       }
  330.  
  331.    XFreeGC(dpy, gc);
  332.    XFreePixmap(dpy, pixmap);
  333.    XFlush(dpy);
  334.    XCloseDisplay(dpy);
  335.  
  336.    Msg4("xmartin: %d points   %d(%d%%) in-range   %d seconds\n",
  337.       nP, np, (100*np)/nP, time(0) - t0);
  338.  
  339.    if (!Recall) {
  340.       sf = fopen(Savefile, "w");
  341.       if (!sf) { perror("xmartin: ~/.xmartin"); exit(1); }
  342.       fprintf(sf, "-f\n%s", fname[Function]);
  343.       (Function == Cp1) && 
  344.      fprintf(sf, ",%d,%u,%u", CpOrder, CpXOrdinal, CpYOrdinal);
  345.       fprintf(sf, "\n-zoom\n%.17e\n", Zf);
  346.       A && fprintf(sf, "-a\n%.17e\n", A);
  347.       B && fprintf(sf, "-b\n%.17e\n", B);
  348.       C && fprintf(sf, "-c\n%.17e\n", C);
  349.       D && fprintf(sf, "-d\n%.17e\n", D);
  350.       x && fprintf(sf, "-x\n%.17e\n", X0);
  351.       y && fprintf(sf, "-y\n%.17e\n", Y0);
  352.       Pn && fprintf(sf, "-perturb\n%d,%.17e\n", Pn, Pv);
  353.       (Tx != 1 || Ty != 1) && fprintf(sf, "-tile\n%dx%d\n", Tx, Ty);
  354.       Move && fprintf(sf, "-move\n%s\n", Move);
  355.       Coord && fprintf(sf, "-coord\n%s\n", coords[Coord]);
  356.       fclose(sf);
  357.       }
  358.    }
  359.  
  360.  
  361. #define Rmod 536870911
  362. #define Rmul 3.99
  363. #define Ranfset(l) (ranfseed=((long)((abs(l)%Rmod)*Rmul))%Rmod)
  364. long    ranfseed=268435456;
  365.  
  366. double ranf() {
  367.    ranfseed = (long) (ranfseed*Rmul)%Rmod;
  368.    return(ranfseed/(double)Rmod);
  369.    }
  370.  
  371.  
  372. int pr_Argv(), pr_colorsort(), pr_intArg(), pr_rangeArg();
  373. static Window pr_dwmroot();
  374. unsigned long pr_parsecolor();
  375. extern char *getenv();
  376.  
  377. preset(argc, argv) int argc; char *argv[]; {
  378.    char *display = getenv("DISPLAY"), dir[4], **argv0 = argv, buf[80];
  379.    char *bgarg = NULL;
  380.    Visual *visual;
  381.    int  i, k, mono = 0, argc0 = argc, dist = 0, Grayscale = 0; 
  382.    int dynam = 0, rv = -1, tile = 0, ordinals = 0, coord = 0;
  383.    unsigned long fg, bg;
  384.    double degr = 0;
  385.  
  386.    t0 = time(0); Ranfset(t0);
  387.    for (i=0; i<32; i++) ranf(); /* jump to a more chaotic point in sequence */
  388.    pi = 4 * atan(1.0);
  389.    strcpy(Savefile, getenv("HOME"));
  390.    strcat(Savefile, "/.xmartin");
  391.    fflush(stderr);
  392.  
  393.    /* prescan arguments for "-recall" */
  394.  
  395.    while (++argv, --argc > 0) { 
  396.       if (!strcmp(*argv, "-recall")) {
  397.      sf = fopen(Savefile, "r");
  398.      if (!sf) { perror("xmartin: ~/.xmartin"); exit(1); }
  399.      while(fgets(buf, 80, sf)) {
  400.         buf[strlen(buf)-1] = '\0';
  401.         pr_Argv(buf);
  402.         }
  403.      Recall++; break;
  404.      }
  405.       }
  406.    while (++argv0, --argc0 > 0) { pr_Argv(*argv0); }
  407.  
  408. #define ArgEq(a) (!strcmp(Argv[i],a))
  409. #define Arg (++i < Argc)
  410. #define NoArg ((i+2)>Argc || Argv[i+1][0]=='-' || Argv[i+1][0]=='+')
  411.  
  412.    /*  parse arguments */
  413.  
  414.    for (i=0; i<Argc; i++) {
  415.  
  416.       if      (ArgEq("-mono"))   { mono++; }
  417.       else if (ArgEq("-nrc"))    { Randomcolor = 0; }
  418.       else if (ArgEq("-recall")) {;}
  419.       else if (ArgEq("-rv"))     { mono++; rv = 1; }
  420.       else if (ArgEq("+rv"))     { mono++; rv = 0; }
  421.       else if (ArgEq("-static")) { Dynam = 0; }
  422.       else if (ArgEq("-v"))      { Msg1("xmartin: version 2.%d\n", PATCHLEVEL);}
  423.       else if (ArgEq("-a") && Arg)  { pr_rangeArg(Argv[i], &A); }
  424.       else if (ArgEq("-b") && Arg)  { pr_rangeArg(Argv[i], &B); }
  425.       else if (ArgEq("-c") && Arg)  { pr_rangeArg(Argv[i], &C); }
  426.       else if (ArgEq("-d") && Arg)  { pr_rangeArg(Argv[i], &D); }
  427.       else if (ArgEq("-x") && Arg)  { pr_rangeArg(Argv[i], &x); }
  428.       else if (ArgEq("-y") && Arg)  { pr_rangeArg(Argv[i], &y); }
  429.       else if (ArgEq("-p") && Arg)  { pr_intArg(Argv[i], &mxp); }
  430.       else if (ArgEq("-P") && Arg)  { pr_intArg(Argv[i], &mxP); }
  431.       else if (ArgEq("-nc") && Arg) { pr_intArg(Argv[i], &nC); }
  432.       else if (ArgEq("-display") && Arg) { display=Argv[i]; }
  433.       else if (ArgEq("-coord") && Arg) { 
  434.      coord++;
  435.      if      (ArgEq("xy"))  Coord = 0;  
  436.      else if (ArgEq("yx"))  Coord = 1;  
  437.      else if (ArgEq("ra"))  Coord = 2;  
  438.      else if (ArgEq("ar"))  Coord = 3;  
  439.      else usage();
  440.      }
  441.       else if (ArgEq("-f") && Arg) {
  442.      Function = -1;
  443.      while(++Function < Nfunc){ 
  444.         int nc = strlen(fname[Function]);
  445.         if (!strncmp(fname[Function], Argv[i], nc)) break;
  446.         }
  447.      (Function == Nfunc) && usage();
  448.      if (strlen(Argv[i]) > strlen(fname[Function])) {
  449.         (Function == Cp1) || usage();
  450.             if (sscanf(Argv[i], "cp1,%d,%lu,%lu", 
  451.         &CpOrder, &CpXOrdinal, &CpYOrdinal)==3)   { ordinals++; }
  452.         else if (sscanf(Argv[i], "cp1,%d", &CpOrder))               {;}
  453.         else usage();
  454.         (CpOrder>0) || usage();
  455.         }
  456.      }
  457.       else if (ArgEq("-move") && Arg) {
  458.      if (sscanf(Argv[i], "%lf,%d", °r, &dist)==2)  {;}
  459.      else if (sscanf(Argv[i], "%3[nsew],%d", dir, &dist)==2) {
  460.         for(k=0; k<16; k++) {
  461.            if (!strcmp(dir, compass[k])) { degr = k * 22.5; break; }
  462.            }
  463.         (k == 16) && usage();
  464.         }
  465.      else usage();
  466.      Move = Argv[i];  /* save for output at end to ~/.xmartin */
  467.      (degr < 0 || dist < 0) && usage();
  468.      degr = 450. - degr;
  469.      while (degr > 360) degr -= 360;
  470.      }
  471.       else if (ArgEq("-bg") || ArgEq("-background")) {
  472.      bgarg = (NoArg) ? "random" : Argv[++i]; 
  473.      }
  474.       else if (ArgEq("-dynam")) {
  475.      if (NoArg) dynam++;  
  476.      else       pr_intArg(Argv[++i], &nD);                    
  477.      }
  478.       else if (ArgEq("-perturb")) {
  479.      Pn = pow(10., 1+ranf()*3); Pv = pow(10.,ranf()*3);
  480.      if   (NoArg)                                        {;} 
  481.      else if ( sscanf(Argv[++i], "%d,%lf", &Pn, &Pv)==2) {;}
  482.      else pr_intArg(Argv[i], &Pn);
  483.      }
  484.       else if (ArgEq("-tile")) {
  485.      if (NoArg) tile++;
  486.      else if (sscanf(Argv[++i], "%dx%d", &Tx, &Ty) != 2) usage(); 
  487.      }
  488.       else if (ArgEq("-zoom") && Arg) {
  489.      if (!sscanf(Argv[i], "%lf", &Zf) || Zf <= 0) usage();
  490.      }
  491.       else usage();
  492.  
  493.       }
  494.    /* open display and extract needed values */
  495.  
  496.    dpy = XOpenDisplay(display); 
  497.    if (!dpy) { Msg1("xmartin: Can't open display '%s'.\n", display); exit(1); }
  498.    scr = DefaultScreen(dpy);
  499.    W = (int) DisplayWidth(dpy, scr);
  500.    H = (int) DisplayHeight(dpy, scr);
  501.    DP = (int) DisplayPlanes(dpy, scr);
  502.  
  503.    if (DP > 1) {
  504.       Color++; 
  505.       visual = DefaultVisual(dpy,scr);
  506.       (visual->class==GrayScale || visual->class==StaticGray) && Grayscale++;
  507.       }
  508.  
  509.    w_root = RootWindow(dpy,scr);
  510.    w_root = pr_dwmroot(dpy, w_root); /* search for DEC wm root */
  511.  
  512. {  /* search for swm/tvtwm root (from ssetroot by Tom LaStrange) */
  513. #include <X11/Xatom.h>
  514.    Atom __SWM_VROOT = None;
  515.    Window rootReturn, parentReturn, *children;
  516.    unsigned int numChildren;
  517.  
  518.    __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
  519.    XQueryTree(dpy, w_root, &rootReturn, &parentReturn, &children, &numChildren);
  520.    for (i = 0; i < numChildren; i++) {
  521.       Atom actual_type;
  522.       int actual_format;
  523.       unsigned long nitems, bytesafter;
  524.       Window *newRoot = NULL;
  525.  
  526.       if (XGetWindowProperty (dpy, children[i], __SWM_VROOT,0,1,
  527.          False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter,
  528.          (unsigned char **) &newRoot) == Success && newRoot) {
  529.          w_root = *newRoot; break;
  530.          }
  531.       }
  532.    }
  533.  
  534.    /* color processing */
  535.  
  536.    if (DP==1 || mono) {
  537.       fg = (rv) ? WhitePixel(dpy,scr) : BlackPixel(dpy, scr);
  538.       bg = (rv) ? BlackPixel(dpy,scr) : WhitePixel(dpy, scr);
  539.       }
  540.    else {
  541.       char option[20], *value; 
  542.       char *res = (Grayscale) ? "Gray" : "Color";
  543.  
  544.       if (!bgarg) {
  545.      value = XGetDefault(dpy, "xmartin", "background");
  546.      bgarg = (value) ? value : "random";
  547.      }
  548.  
  549.       if (!strncmp(bgarg, "random",6)) {
  550.      i = Min(Ncolors-1, (int)(ranf()*Ncolors));
  551.      sprintf(option, "bg%s%d", res, i+1);
  552.      value = XGetDefault(dpy, "xmartin", option);
  553.      if (!value) value = (Grayscale) ? bg_grays[i] : bg_colors[i];
  554.      bgarg = value;
  555.      }
  556.       bg = pr_parsecolor(bgarg);
  557.  
  558.       for(i=0; i<Ncolors; i++) {
  559.      sprintf(option, "%s%d", res, i+1);
  560.      value = XGetDefault(dpy, "xmartin", option);
  561.      if (!value) value = (Grayscale) ? fg_grays[i] : fg_colors[i];
  562.      colors[i].c_color = pr_parsecolor(value);
  563.      }
  564.  
  565.       if (Randomcolor) {
  566.      for(i=0; i<Ncolors; i++) colors[i].c_rand =  ranf();
  567.      qsort(colors, Ncolors, sizeof(struct colors), pr_colorsort);
  568.      }
  569.       fg = colors[0].c_color;
  570.  
  571.       }
  572.  
  573.  
  574.    /* provide default hopalong parameters if needed */ 
  575.  
  576.    if (Function < 0) {
  577.       double p=0, r = ranf();
  578.       for(Function=0; Function <Nfunc; Function++) {
  579.      p += fprob[Function];
  580.      if (r < p) break;
  581.      }
  582.       }
  583.  
  584.    if (tile) {
  585.       int mxt = (Function == Cp1) ? 4 : 8;
  586.       while ((Tx+Ty) == 2 ) {
  587.      Tx = (int)(ranf()*mxt + 1);
  588.      Ty = (int)(ranf()*mxt + 1);
  589.      }
  590.       }
  591.  
  592.    W /= Tx; H /= Ty;
  593.    if (W==0||H==0) { Msg("xmartin: tile too small for display\n"); exit(1); }
  594.  
  595.    if (mxp > 0 && mxp <= 100) mxp = (mxp*W*H)/100.;
  596.    if (mxP > 0 && mxP <= 100) mxP = (mxP*W*H)/100.;
  597.  
  598.    if (!mxp && !mxP) {
  599.       mxp = (int) ((Function == Cp1) ? 200000 : 0.25 * (float)(W*H));
  600.       mxP = (Function >= Cp1) ? mxp : 3 * mxp;
  601.       }
  602.    else if (!mxp) mxp = mxP;
  603.    else if (!mxP) mxP = (Function >= Cp1) ? mxp : 3 * mxp;
  604.  
  605.    if (!nD) nD = (Tx == 1 && Ty == 1) ? 1024 : 128;
  606.    if (!nC) nC = mxP/Ncolors;
  607.  
  608.    cx = W/2; cy = H/2; mxX = W-1; mxY = H-1;
  609.    if (dist) { 
  610.       cx += dist * cos(degr * (pi/180)); 
  611.       cy -= dist * sin(degr * (pi/180));
  612.       }
  613.  
  614.    if (Function == Martin1) {
  615.       A || pr_rangeArg("40::1540",  &A);
  616.       B || pr_rangeArg("3::20",     &B);
  617.       C || pr_rangeArg("100::3100", &C);
  618.       if (!Zf) Zf = 1.0;
  619.       }
  620.    else if (Function == Martin2) {
  621.       A || pr_rangeArg("3.0715927::3.2115927",  &A);
  622.       if (!Zf) Zf = 4.0;
  623.       }
  624.    else if (Function == Ejk1) {
  625.       A || pr_rangeArg("0::500", &A);
  626.       B || pr_rangeArg("0::.40", &B);
  627.       C || pr_rangeArg("10::110", &C);
  628.       if (!Zf) Zf = 1.0;
  629.       }
  630.    else if (Function == Ejk2) {
  631.       A || pr_rangeArg("0::500", &A);
  632.       if (!B) { B = pow(10.,6+ranf()*24); if (ranf()<0.5) B = -B; }
  633.       if (!C) { C = pow(10.,  ranf()*9);  if (ranf()<0.5) C = -C; }
  634.       if (!Zf) Zf = 1.0;
  635.       }
  636.    else if (Function == Ejk3) {
  637.       A || pr_rangeArg("0::500", &A);
  638.       B || pr_rangeArg(".05::.40", &B);
  639.       C || pr_rangeArg("30::110", &C);
  640.       if (!Zf) Zf = 1.0;
  641.       }
  642.    else if (Function == Ejk4) {
  643.       A || pr_rangeArg("0::1000", &A);
  644.       B || pr_rangeArg("1::10", &B);
  645.       C || pr_rangeArg("30:70", &C);
  646.       if (!Zf) Zf = 0.7;
  647.       }
  648.    else if (Function == Ejk5) {
  649.       A || pr_rangeArg("0::600", &A);
  650.       B || pr_rangeArg(".1::.4", &B);
  651.       C || pr_rangeArg("20::110", &C);
  652.       if (!Zf) Zf = 0.7;
  653.       }
  654.    else if (Function == Ejk6) {
  655.       A || pr_rangeArg("550:650", &A);
  656.       B || pr_rangeArg(".5::1.5", &B);
  657.       if (!Zf) Zf = 1.2;
  658.       if (!Move) {
  659.      Move = "320,500";
  660.      sscanf(Move, "%lf,%d", °r, &dist);
  661.      cx += dist * cos((450.-degr)*(pi/180.));
  662.      cy -= dist * sin((450.-degr)*(pi/180.));
  663.          }
  664.       }
  665.    else if (Function == Rr1) {
  666.       A || pr_rangeArg("0::100", &A);
  667.       B || pr_rangeArg("0::20", &B);
  668.       C || pr_rangeArg("0::200", &C);
  669.       D || pr_rangeArg("0:.9", &D);
  670.       if (!Zf) { 
  671.      if      (D < .2) Zf = 10;
  672.      else if (D < .4) Zf = 5;
  673.      else if (D < .5) Zf = 3;
  674.      else if (D < .7) Zf = 1;
  675.      else             Zf = .5;
  676.      }
  677.       }
  678.    else if (Function == Cp1) {
  679.       unsigned long mxord, ord, o;
  680.       if (CpOrder) {
  681.      if (CpOrder > 16) {
  682.         Msg("xmartin: maximum order 16 for cp1 sine series\n");
  683.         exit(1);
  684.         }
  685.          mxord = 1; 
  686.      for (k=0; k<CpOrder; k++) mxord *= 4; 
  687.      mxord -= 1;
  688.      if (CpXOrdinal > mxord || CpYOrdinal > mxord) {
  689.         Msg2("xmartin: %d maximum ordinal for order %d cp1 sine series.\n",
  690.           mxord, CpOrder);
  691.         exit(1);
  692.         }
  693.      else if (!ordinals) {
  694.         CpXOrdinal = ranf() * mxord + 0.5;
  695.         CpYOrdinal = ranf() * mxord + 0.5;
  696.         }
  697.      }
  698.       else {
  699.      CpOrder = 3 + ranf()*7;
  700.          mxord = 1; 
  701.      for (k=0; k<CpOrder; k++) mxord *= 4; 
  702.      CpXOrdinal = ranf() * mxord + 0.5;
  703.      CpYOrdinal = ranf() * mxord + 0.5;
  704.      }
  705.       
  706.       if (!B) { B = (5 + (int)(ranf()*6)) + ranf(); if (ranf()<0.5) B = -B; }
  707.       if (!A) { A = ((int)(1 + ranf()*4) * B);      if (ranf()<0.5) A = -A;}
  708.       if (!x) { x = 20; }
  709.       if (!y) { y = 30; }
  710.       if (!Zf) { Zf = cp_zoom[CpOrder-1]; }
  711.       if (!Grayscale && nC == mxP/Ncolors) nC = mxP;
  712.       if (!coord) { Coord = (int)(ranf()*4); coord++; }
  713.       if (!Move && (Coord == XY || Coord == YX) ) {
  714.      Move = cp_move[CpOrder-1];
  715.      sscanf(Move, "%lf,%d", °r, &dist);
  716.      cx += dist * cos((450.-degr)*(pi/180.));
  717.      cy -= dist * sin((450.-degr)*(pi/180.));
  718.          }
  719.       }
  720.  
  721.    X0 = x; Y0 = y;
  722.  
  723.    /* allocate resources needed for pattern */
  724.  
  725.    if (Dynam) {
  726.       gc = XCreateGC(dpy, w_root, 0, (XGCValues *)0);
  727.       pixmap = XCreatePixmap( dpy, w_root, W, H, DP);
  728.       if (!pixmap) { Msg("xmartin: XCreatePixmap error\n"); exit(1); }
  729.  
  730.       XSetForeground(dpy, gc, bg);
  731.       XFillRectangle(dpy, pixmap, gc, 0, 0, W, H);
  732.       XSetForeground(dpy, gc, fg);
  733.       XSetBackground(dpy, gc, bg);
  734.  
  735.       XSetWindowBackgroundPixmap(dpy, w_root, pixmap);
  736.       xpoints =  (XPoint *)malloc((unsigned)(nD * sizeof(XPoint)));
  737.       if (!xpoints) { Msg("xmartin: malloc failed.\n"); exit(1); }
  738.       }
  739.    else {
  740.       bmn = ((W+7)/8) * H * DP;
  741.       bmap = (char *) malloc((unsigned)bmn);
  742.       if (!bmap) { Msg("xmartin: malloc failed.\n"); exit(1); }
  743.       bzero(bmap, bmn);
  744.       Xi = XCreateImage
  745.               (dpy, DefaultVisual(dpy,scr), DP, XYPixmap, 0, bmap, W, H, 8, 0);
  746.       if (!Xi) { Msg("xmartin: XCreateImage error.\n"); exit(1); }
  747.       Xi->bitmap_unit = 8;
  748.       Xi->bitmap_bit_order = LSBFirst;
  749.       wc = Xi->bytes_per_line;
  750.  
  751.       pixel = bg;
  752.       offset = (DP-1) * wc * H;
  753.       for (plane=0; plane <DP; plane++) {
  754.      if (pixel & 1) 
  755.         for (k=0; k<wc*H; k++) bmap[offset+k] = 0377;
  756.      pixel >>= 1;
  757.      offset -= wc * H;
  758.      }
  759.       pixel = fg;
  760.       }
  761.  
  762.    /* display pattern parameters */
  763.  
  764.    Msg("xmartin:------------------------------------------------------------");
  765.    Msg("\n");
  766.    Msg2("xmartin: %dx%d ", W, H);
  767.    (DP > 1) ? Msg2("%d-plane %s", DP, (Grayscale) ? "grayscale" : "color") 
  768.             : Msg("monochrome");
  769.    Msg1(" %s", (Dynam) ? "dynamic" : "static");
  770.    Color && Msg1("  background: %s", bgarg);
  771.    Msg("\n");
  772.  
  773.  
  774.    Msg1("xmartin: -f %s", fname[Function]);
  775.    if (Function == Cp1) Msg3(",%d,%u,%u", CpOrder, CpXOrdinal, CpYOrdinal);
  776.    Msg1(" -a %g ", A);
  777.    B &&  Msg1("-b %g ", B);
  778.    C &&  Msg1("-c %g ", C);
  779.    D &&  Msg1("-d %g ", D);
  780.    x &&  Msg1("-x %g ", x);
  781.    y &&  Msg1("-y %g ", y);
  782.    Msg("\n");
  783.  
  784.    if (coord || Pn || Move || (Zf + Tx + Ty) != 3) {
  785.       Msg("xmartin: ");
  786.       Pn && Msg2("-perturb %d,%.1f ", Pn, Pv);
  787.       coord && Msg1("-coord %s ", coords[Coord]);
  788.       Move && Msg1("-move %s ", Move);
  789.       if (Zf != 1) Msg1("-zoom %.2f ", Zf);
  790.       if (Tx!=1 || Ty!=1) Msg2("-tile %dx%d ", Tx, Ty);
  791.       Msg("\n");
  792.       }
  793.    }
  794.  
  795.  
  796. pr_Argv(s) char *s; {
  797.    Argv = (Argc) ? (char **) realloc ((char *)Argv, (Argc+1) * sizeof(char *))
  798.                  : (char **) malloc  (sizeof(char *));
  799.    Argv[Argc++] = (s) ? strcpy((char *) malloc (strlen(s)+1), s) : NULL;
  800.    }
  801.  
  802.  
  803. pr_colorsort(a,b) struct colors *a, *b; { 
  804.    double d = a->c_rand - b->c_rand;
  805.    if (d < 0) return(-1);
  806.    else if (d > 0) return(1);
  807.    else return(0);
  808.    }
  809.  
  810.  
  811. static Window 
  812. pr_dwmroot(dpy, pwin) Display *dpy; Window  pwin; {
  813.    /* search for DEC Window Manager root */
  814.    XWindowAttributes pxwa,cxwa;
  815.    Window  root,parent,*child;
  816.    unsigned int i, nchild;
  817.  
  818.    if (!XGetWindowAttributes(dpy,pwin,&pxwa)) Msg("xmartin: XGWA failed\n");
  819.    if (XQueryTree(dpy,pwin,&root,&parent,&child,&nchild)) {
  820.       for (i = 0; i < nchild; i++) {
  821.          if (!XGetWindowAttributes(dpy,child[i],&cxwa))
  822.             Msg("xmartin: XGWA failed\n");
  823.          if (pxwa.width == cxwa.width && pxwa.height == cxwa.height)
  824.             return(pr_dwmroot(dpy, child[i]));
  825.          }
  826.         return(pwin);
  827.       }
  828.    else Msg("xmartin: failed to find root window\n");
  829.    exit(1);
  830.    }
  831.  
  832.  
  833. pr_intArg(arg,i) char *arg; int *i; {
  834.    if(!sscanf(arg, "%d", i) || *i <= 0) usage();
  835.    }
  836.  
  837.  
  838. unsigned long
  839. pr_parsecolor(arg) char *arg; {
  840.    char color[30];
  841.    double intensity = -1;
  842.    XColor xcolor;
  843.  
  844.    if (sscanf(arg,"%30[^,],%lf", color, &intensity) == 2) {
  845.       if (intensity < 0 || intensity > 1) {
  846.      Msg1("xmartin: invalid color intensity in '%s'\n", color);
  847.      intensity = 1;
  848.      }
  849.       }
  850.    else strcpy(color, arg);
  851.  
  852.    if (intensity < 0) intensity = 1;
  853.  
  854.    if (!XParseColor(dpy, DefaultColormap(dpy,scr), color, &xcolor)) {
  855.       Msg1("xmartin: unable to parse '%s'. Using white.\n", color);
  856.       return((unsigned long) WhitePixel(dpy,scr));
  857.       }
  858.    else {
  859.       xcolor.red *= intensity;
  860.       xcolor.green *= intensity;
  861.       xcolor.blue *= intensity;
  862.       if (XAllocColor(dpy, DefaultColormap(dpy,scr), &xcolor)) {
  863.      return(xcolor.pixel);
  864.      }
  865.       else {
  866.      Msg1("xmartin: can't allocate '%s'. Using white.\n", arg);
  867.      return((unsigned long) WhitePixel(dpy,scr));
  868.      }
  869.       }
  870.    }
  871.  
  872. pr_rangeArg(arg,x) char *arg; double *x; {
  873.    double x2=0; int xf = 0; 
  874.  
  875.    if      ( sscanf(arg, "%lf::%lf", x, &x2) == 2) { xf++; }
  876.    else if ( sscanf(arg, "%lf:%lf",  x, &x2) == 2) { ; }
  877.    else if (!sscanf(arg, "%lf",      x))           { usage(); }
  878.    if (x2) {
  879.       *x = Min(*x,x2) + ranf()*(Max(*x,x2) - Min(*x,x2));
  880.       if (xf && ranf()<0.5) *x = -(*x);
  881.       }
  882.    }
  883.  
  884.  
  885. usage() { 
  886.    int f = -1; 
  887.    Msg("usage: xmartin\n");
  888.    Msg1("[-f {%s", fname[++f]);
  889.    while (++f < Nfunc) Msg1("|%s", fname[f]); 
  890.    Msg("}]\n");
  891.    Msg("[-f cp1[,order[,xn,yn]]]");
  892.    Msg("\n");
  893.    Msg("[-a real[[:]:real]] "); 
  894.    Msg("[-b real[[:]:real]] "); 
  895.    Msg("[-c real[[:]:real]] "); 
  896.    Msg("\n");
  897.    Msg("[-d real[[:]:real]] "); 
  898.    Msg("[-x real[[:]:real]] "); 
  899.    Msg("[-y real[[:]:real]] "); 
  900.    Msg("\n");
  901.    Msg("[-p npoints] "); 
  902.    Msg("[-P npoints] "); 
  903.    Msg("[-dynam [nd]] "); 
  904.    Msg("[-static] "); 
  905.    Msg("\n");
  906.    Msg("[-bg [color[,intensity]]] ");
  907.    Msg("[-nc npoints] "); 
  908.    Msg("[+rv] [-rv] "); 
  909.    Msg("[-mono] "); 
  910.    Msg("[-nrc]"); 
  911.    Msg("\n");
  912.    Msg("[-tile [XxY]] "); 
  913.    Msg("[-perturb [n[,v]]] "); 
  914.    Msg("[-coord {xy|yx|ra|ar}]");
  915.    Msg("\n");
  916.    Msg("[-zoom real] "); 
  917.    Msg("[-move d,p] "); 
  918.    Msg("\n");
  919.    Msg("[-recall] "); 
  920.    Msg("[-display display] "); 
  921.    Msg("[-v]"); 
  922.    Msg("\n"); 
  923.    exit(1); 
  924.    }
  925.